/**
 * @file logger.c
 * @brief 通用日志系统实现文件
 * @author 开发者
 * @date 2024
 */

#include "logger.h"
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

// 默认配置
const log_config_t LOGGER_DEFAULT_CONFIG = {
    .level = LOG_LEVEL_INFO,
    .target = LOG_TARGET_CONSOLE,
    .file_path = NULL,
    .max_file_size = 10 * 1024 * 1024,  // 10MB
    .max_files = 5,
    .color_output = true,
    .timestamp = true,
    .thread_id = false,
    .file_line = true,
    .async_output = false,
    .buffer_size = 4096
};

// 全局变量
static log_config_t g_config = LOGGER_DEFAULT_CONFIG;
static log_stats_t g_stats = {0};
static FILE *g_log_file = NULL;
static pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool g_initialized = false;

// 颜色代码
#define COLOR_RESET   "\033[0m"
#define COLOR_TRACE   "\033[37m"  // 白色
#define COLOR_DEBUG   "\033[36m"  // 青色
#define COLOR_INFO    "\033[32m"  // 绿色
#define COLOR_TEST    "\033[35m"  // 紫色
#define COLOR_WARN    "\033[33m"  // 黄色
#define COLOR_ERROR   "\033[31m"  // 红色
#define COLOR_FATAL   "\033[41m"  // 红色背景

// 级别字符串
static const char* LEVEL_STRINGS[] = {
    "TRACE", "DEBUG", "INFO", "TEST", "WARN", "ERROR", "FATAL"
};

// 级别颜色
static const char* LEVEL_COLORS[] = {
    COLOR_TRACE, COLOR_DEBUG, COLOR_INFO, COLOR_TEST, 
    COLOR_WARN, COLOR_ERROR, COLOR_FATAL
};

// 内部函数声明
static void logger_output(const char *message);
static void logger_rotate_file(void);
static void logger_update_stats(log_level_t level);
static void logger_format_message(char *buffer, size_t size, log_level_t level, 
                                 const char *file, int line, const char *func, 
                                 const char *format, va_list args);

// 初始化日志系统
int logger_init(const log_config_t *config) {
    if (g_initialized) {
        return 0;
    }
    
    if (config) {
        g_config = *config;
    }
    
    // 初始化统计信息
    memset(&g_stats, 0, sizeof(g_stats));
    g_stats.start_time = time(NULL);
    
    // 设置文件输出
    if (g_config.target == LOG_TARGET_FILE && g_config.file_path) {
        g_log_file = fopen(g_config.file_path, "a");
        if (!g_log_file) {
            fprintf(stderr, "错误: 无法打开日志文件 %s: %s\n", 
                    g_config.file_path, strerror(errno));
            return -1;
        }
        
        // 设置文件缓冲
        if (g_config.async_output) {
            setvbuf(g_log_file, NULL, _IOLBF, g_config.buffer_size);
        } else {
            setvbuf(g_log_file, NULL, _IONBF, 0);
        }
    }
    
    g_initialized = true;
    LOG_INFO("日志系统初始化完成");
    return 0;
}

// 清理日志系统
void logger_cleanup(void) {
    if (!g_initialized) {
        return;
    }
    
    LOG_INFO("日志系统正在关闭...");
    
    if (g_log_file) {
        fclose(g_log_file);
        g_log_file = NULL;
    }
    
    pthread_mutex_destroy(&g_log_mutex);
    g_initialized = false;
}

// 设置日志级别
void logger_set_level(log_level_t level) {
    g_config.level = level;
    LOG_INFO("日志级别设置为: %s", logger_level_to_string(level));
}

// 获取当前日志级别
log_level_t logger_get_level(void) {
    return g_config.level;
}

// 设置日志输出目标
int logger_set_target(log_target_t target, const char *file_path) {
    if (target == LOG_TARGET_FILE && !file_path) {
        return -1;
    }
    
    // 关闭当前文件
    if (g_log_file) {
        fclose(g_log_file);
        g_log_file = NULL;
    }
    
    g_config.target = target;
    
    if (target == LOG_TARGET_FILE) {
        g_config.file_path = strdup(file_path);
        g_log_file = fopen(file_path, "a");
        if (!g_log_file) {
            fprintf(stderr, "错误: 无法打开日志文件 %s: %s\n", 
                    file_path, strerror(errno));
            return -1;
        }
        
        if (g_config.async_output) {
            setvbuf(g_log_file, NULL, _IOLBF, g_config.buffer_size);
        } else {
            setvbuf(g_log_file, NULL, _IONBF, 0);
        }
    }
    
    return 0;
}

// 启用/禁用彩色输出
void logger_set_color(bool enable) {
    g_config.color_output = enable;
}

// 启用/禁用时间戳
void logger_set_timestamp(bool enable) {
    g_config.timestamp = enable;
}

// 启用/禁用线程ID显示
void logger_set_thread_id(bool enable) {
    g_config.thread_id = enable;
}

// 启用/禁用文件名和行号显示
void logger_set_file_line(bool enable) {
    g_config.file_line = enable;
}

// 启用/禁用异步输出
void logger_set_async(bool enable) {
    g_config.async_output = enable;
}

// 获取日志统计信息
void logger_get_stats(log_stats_t *stats) {
    if (stats) {
        *stats = g_stats;
    }
}

// 重置日志统计信息
void logger_reset_stats(void) {
    memset(&g_stats, 0, sizeof(g_stats));
    g_stats.start_time = time(NULL);
}

// 刷新日志缓冲区
void logger_flush(void) {
    if (g_log_file) {
        fflush(g_log_file);
    }
    fflush(stdout);
    fflush(stderr);
}

// 轮转日志文件
int logger_rotate(void) {
    if (g_config.target != LOG_TARGET_FILE || !g_config.file_path) {
        return -1;
    }
    
    logger_rotate_file();
    return 0;
}

// 日志输出函数
void logger_log(log_level_t level, const char *file, int line, const char *func, 
                const char *format, ...) {
    if (!g_initialized || level < g_config.level || level >= LOG_LEVEL_OFF) {
        return;
    }
    
    char buffer[4096];
    va_list args;
    va_start(args, format);
    logger_format_message(buffer, sizeof(buffer), level, file, line, func, format, args);
    va_end(args);
    
    pthread_mutex_lock(&g_log_mutex);
    logger_output(buffer);
    logger_update_stats(level);
    pthread_mutex_unlock(&g_log_mutex);
}

// 输出日志消息
static void logger_output(const char *message) {
    switch (g_config.target) {
        case LOG_TARGET_CONSOLE:
            if (g_config.color_output) {
                fprintf(stderr, "%s", message);
            } else {
                fprintf(stderr, "%s", message);
            }
            break;
            
        case LOG_TARGET_FILE:
            if (g_log_file) {
                fprintf(g_log_file, "%s", message);
                if (!g_config.async_output) {
                    fflush(g_log_file);
                }
                
                // 检查文件大小，需要轮转
                fseek(g_log_file, 0, SEEK_END);
                long file_size = ftell(g_log_file);
                if (file_size > (long)g_config.max_file_size) {
                    logger_rotate_file();
                }
            }
            break;
            
        case LOG_TARGET_SYSLOG:
            // TODO: 实现syslog输出
            fprintf(stderr, "%s", message);
            break;
            
        case LOG_TARGET_NETWORK:
            // TODO: 实现网络输出
            fprintf(stderr, "%s", message);
            break;
    }
}

// 轮转日志文件
static void logger_rotate_file(void) {
    if (!g_log_file || !g_config.file_path) {
        return;
    }
    
    fclose(g_log_file);
    
    // 重命名现有文件
    for (int i = g_config.max_files - 1; i > 0; i--) {
        char old_name[512], new_name[512];
        if (i == 1) {
            snprintf(old_name, sizeof(old_name), "%s", g_config.file_path);
        } else {
            snprintf(old_name, sizeof(old_name), "%s.%d", g_config.file_path, i - 1);
        }
        snprintf(new_name, sizeof(new_name), "%s.%d", g_config.file_path, i);
        
        rename(old_name, new_name);
    }
    
    // 重新打开文件
    g_log_file = fopen(g_config.file_path, "w");
    if (g_log_file) {
        if (g_config.async_output) {
            setvbuf(g_log_file, NULL, _IOLBF, g_config.buffer_size);
        } else {
            setvbuf(g_log_file, NULL, _IONBF, 0);
        }
    }
}

// 更新统计信息
static void logger_update_stats(log_level_t level) {
    g_stats.total_count++;
    g_stats.last_log_time = time(NULL);
    
    switch (level) {
        case LOG_LEVEL_TRACE:
            g_stats.trace_count++;
            break;
        case LOG_LEVEL_DEBUG:
            g_stats.debug_count++;
            break;
        case LOG_LEVEL_INFO:
            g_stats.info_count++;
            break;
        case LOG_LEVEL_TEST:
            g_stats.test_count++;
            break;
        case LOG_LEVEL_WARN:
            g_stats.warn_count++;
            break;
        case LOG_LEVEL_ERROR:
            g_stats.error_count++;
            break;
        case LOG_LEVEL_FATAL:
            g_stats.fatal_count++;
            break;
        default:
            break;
    }
}

// 格式化日志消息
static void logger_format_message(char *buffer, size_t size, log_level_t level, 
                                 const char *file, int line, const char *func, 
                                 const char *format, va_list args) {
    char timestamp[64] = {0};
    char thread_id[16] = {0};
    char file_line[256] = {0};
    char message[2048] = {0};
    
    // 格式化时间戳
    if (g_config.timestamp) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        struct tm *tm_info = localtime(&tv.tv_sec);
        strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm_info);
        snprintf(timestamp + 19, sizeof(timestamp) - 19, ".%06ld", tv.tv_usec);
    }
    
    // 格式化线程ID
    if (g_config.thread_id) {
        snprintf(thread_id, sizeof(thread_id), "[%lu]", pthread_self());
    }
    
    // 格式化文件名和行号
    if (g_config.file_line) {
        const char *filename = strrchr(file, '/');
        filename = filename ? filename + 1 : file;
        snprintf(file_line, sizeof(file_line), "[%s:%d:%s]", filename, line, func);
    }
    
    // 格式化消息内容
    vsnprintf(message, sizeof(message), format, args);
    
    // 组合最终消息
    const char *color_start = g_config.color_output ? LEVEL_COLORS[level] : "";
    const char *color_end = g_config.color_output ? COLOR_RESET : "";
    
    snprintf(buffer, size, "%s[%s]%s%s%s%s %s%s\n",
             color_start,
             LEVEL_STRINGS[level],
             color_end,
             timestamp[0] ? " " : "",
             timestamp,
             thread_id,
             file_line,
             message);
}

// 级别转字符串
const char* logger_level_to_string(log_level_t level) {
    if (level >= 0 && level < sizeof(LEVEL_STRINGS) / sizeof(LEVEL_STRINGS[0])) {
        return LEVEL_STRINGS[level];
    }
    return "UNKNOWN";
}

// 级别转颜色
const char* logger_level_to_color(log_level_t level) {
    if (level >= 0 && level < sizeof(LEVEL_COLORS) / sizeof(LEVEL_COLORS[0])) {
        return LEVEL_COLORS[level];
    }
    return COLOR_RESET;
}

// 字符串转级别
log_level_t logger_string_to_level(const char *level_str) {
    if (!level_str) {
        return LOG_LEVEL_INFO;
    }
    
    for (size_t i = 0; i < sizeof(LEVEL_STRINGS) / sizeof(LEVEL_STRINGS[0]); i++) {
        if (strcasecmp(level_str, LEVEL_STRINGS[i]) == 0) {
            return (log_level_t)i;
        }
    }
    
    return LOG_LEVEL_INFO;
}
